#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/kd.h>
#include <linux/tty.h>
#include <linux/vt_kern.h>
#include <linux/console_struct.h>

#define NOMBRE "theleds"
static struct proc_dir_entry *procentry;
int bin2dec(char*);
char buffer[4];
int n;

//Funcion que se invoca cuando se escribe la entrada en /proc
int onwrite( struct file *filp, const char __user *buff, unsigned long len, void *data ){
	//copio los primeros 3 bytes de la entrada
	copy_from_user(buffer,buff,3);buffer[3]=0;
	n=bin2dec(buffer); //Convierto de binario a entero
	printk(KERN_ALERT "oi! %d\n",n);
	//llamada a la funcion ioctl para modificar el estado de los leds
	(vc_cons[fg_console].d->vc_tty->driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED, n);
	return len;
}

//Funcion que se invoca al cargar el modulo
static int __init leds_init(void){
	printk(KERN_INFO "leds loaded.\n");
	//creo la entrada en /proc
	procentry=create_proc_entry( NOMBRE, 0666, NULL );
	//callback cuando ocurre escritura
	procentry->write_proc=onwrite;
	return 0;
}

static void __exit leds_exit(void){
	//elimino la entrada en /proc
	remove_proc_entry( NOMBRE, NULL );
	printk(KERN_INFO "leds unloaded.\n");
	return;
}

MODULE_LICENSE("GPL");
module_init( leds_init );
module_exit( leds_exit );

int bin2dec(char *bin){
	//funcion que convierte un string binario a un entero
	int k,sum=0,len=strlen(bin)-1;
	for(k=0;k<=len;k++) sum+=(bin[k]-'0')*(1<<(len-k));
	return sum;
}
